package org.tigr.htc.cmd;

/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

import java.io.Reader;
import java.io.StringWriter;

import org.apache.log4j.Logger;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.tigr.htc.common.HTCConfig;

/**
 * The <b>CommandHelper</b> handles the interface to the XML marshaller
 * (castor). CommandHelper knows how to convert the java classes in the
 * cmd package into XML and XML documents into java object.
 */
public class CommandHelper {
    static Logger log = Logger.getLogger(CommandHelper.class);
    
    /**
     * <code>defaultConfig</code> default place to find CommandMapping file.
     *
     */
    protected String defaultConfig = HTCConfig.getProperty("CommandMap");
    
    /**
     * <code>chelper</code> singleton reference
     *
     */
    static final private CommandHelper chelper = new CommandHelper();
    
    protected Mapping mp;
    protected Unmarshaller unmar;
    
    /**
     * Creates a new <code>CommandHelper</code> instance.
     * Load castor mapping file and create a unmarshaller.
     *
     */
    private CommandHelper() {
        if(mp == null) {
            try {
                mp = new Mapping();
                log.debug(" Using mapping file:" + defaultConfig);
                mp.loadMapping(defaultConfig);
                unmar = new Unmarshaller(mp);
            } catch (Exception e) { 
                log.fatal(" Mapping IO error for mapping file " + defaultConfig 
                        + " -> " + e.getMessage() + "<-", e);
                return;
            } 
        }
    }
    
    
    /**
     * <code>getInstance</code> get or create the CommandHelper singleton
     * instance.
     *
     * @return a <code>CommandHelper</code> value
     */
    public static CommandHelper getInstance() {
        return chelper;
    }
    
    /**
     * <code>marshal</code> java object to xml.
     * Object must have a predefined mapping for Castor.
     *
     * @param p_obj an <code>Object</code> to marshal to xml
     * @return a <code>String</code> value
     */
    public String marshal(Object p_obj) {
        StringWriter strWriter = new StringWriter();
        
        try {
            Marshaller mar = new Marshaller(strWriter);
            mar.setMapping(mp);
            mar.marshal(p_obj);
            return strWriter.toString();
        } catch (Exception e) {
            log.error(" marshaller failed " + e.getMessage(), e);
            return "Marshaller failed" + e.getMessage();
        }
    }
    
    /**
     * <code>unmarshal</code> xml document into java objects.
     * XML document must be in the Castor mapping file.
     *
     * @param p_str a <code>Reader</code> to read xml from.
     * @return an <code>Object</code> return java objects describe in XML.
     * @exception Exception if an error occurs
     */
    public Object unmarshal(Reader p_str) throws Exception {
        try {
            return unmar.unmarshal(p_str);
        }
        catch (Exception e) {
            log.error(" unmarshaller failed " + e.getMessage(), e);
            throw new Exception(e.getMessage());
        }
    }
    
    /**
     * <code>unmarshalRoot</code> unmarshal a CommandSetRoot document.
     * All commands and commandset are set enclosed in a CommandSetRoot.
     *
     * @param p_strCom a <code>Reader</code> to read xml from.
     * @return a <code>CommandSetRoot</code> object
     * @exception Exception if a unmarshaller
     */
    public CommandSetRoot unmarshalRoot(Reader p_strCom) 
    throws Exception {
        try {
            return (CommandSetRoot) unmar.unmarshal(p_strCom);
        } catch (Exception e) {
            log.error(" unmarshaller failed " + e.getMessage(), e);
            throw new Exception(e.getMessage());
        }
    }
    
}
